package com.example.jpademo.ref.generate.impl;

import com.example.jpademo.ref.generate.IAuthManagerService;
import com.example.jpademo.ref.generate.enums.AuthInsertSQL;
import com.example.jpademo.ref.generate.enums.CommonIdIncrSQL;
import com.example.jpademo.ref.generate.vo.AuthManageDTO;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;

@Service
@ConditionalOnProperty(
        prefix = "devtool",
        value = {"refgenerate"},
        havingValue = "true",
        matchIfMissing = false
)
public class AuthManagerServiceImpl implements IAuthManagerService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private JdbcTemplate jdbcTemplate;
    public AuthManagerServiceImpl() {
        jdbcTemplate = new JdbcTemplate(dataSource(),true);
    }


    @Override
    public void createAuthManage(AuthManageDTO auth) {
        this.createAuthManage(auth,true);
    }

    @Override
    public String createAuthManageSql(AuthManageDTO auth) {
        return this.createAuthManage(auth,false);
    }


    private String createAuthManage(AuthManageDTO auth,boolean execute){
        Objects.requireNonNull(auth,"数据权限对象不能为null");
        Objects.requireNonNull(auth.getRefCode(),"数据权限的参照编码不能为null");
        Objects.requireNonNull(auth.getRefName(),"数据权限的参照说明不能为null");
        Objects.requireNonNull(auth.getMetauri(),"数据权限的元数据uri不能为null");
        Objects.requireNonNull(auth.getRefdomain(),"数据权限的领域domain不能为null");
        String detailCode = StringUtils.isEmpty(auth.getDetailCode())?auth.getRefCode():auth.getDetailCode();
        String detailName = StringUtils.isEmpty(auth.getDetailName())?auth.getRefName():auth.getDetailName();
        return this.createAuthData(auth.getRefCode(),auth.getRefName(),auth.getMetauri(),auth.getRefdomain(),
                detailCode,detailName,execute);
    }

    private String createAuthData(String refCode,String refName,String metauri,String refdomain,
                               String detailCode,String detailName, boolean execute){
        return this.createAuthIds(true) + ";\n" +
                this.createAuthManage(refCode, refName, metauri, refdomain, detailCode, detailName, execute);
    }


    private String createAuthManage(String refCode,String refName,String metauri,String refdomain,
                                   String detailCode,String detailName, boolean execute){
        String mainSQL = String.format(AuthInsertSQL.AUTH_MAIN.getSql(),refCode,refName,metauri,refdomain);
        String subSQL = String.format(AuthInsertSQL.AUTH_SUB.getSql(),detailCode,detailName,metauri,refCode,refdomain);
        if(execute){
            jdbcTemplate.batchUpdate(mainSQL,subSQL);
        }
        return String.join(";\n",mainSQL,subSQL);
    }

    private String createAuthIds(boolean execute){
        if(execute) {
            Arrays.asList(
                    CommonIdIncrSQL.AUTH_MAIN_ID.getSql(),
                    CommonIdIncrSQL.AUTH_SUB_ID.getSql()
            ).forEach(sql -> jdbcTemplate.execute(sql));
        }
        String sql = String.join(";\n",
                CommonIdIncrSQL.AUTH_MAIN_ID.getSql(),
                CommonIdIncrSQL.AUTH_SUB_ID.getSql());
        System.out.println(sql);
        return sql;
    }

    private DataSource dataSource(){
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties");
        Properties props = new Properties();
        try {
            props.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return DataSourceBuilder.create()
                .driverClassName(props.getProperty("auth.db.driver-class-name"))
                .url(props.getProperty("auth.db.jdbc-url"))
                .username(props.getProperty("auth.db.username"))
                .password(props.getProperty("auth.db.password"))
                .type(HikariDataSource.class)
                .build();
    }
}
